package com.bjpowernode.aop;

import com.bjpowernode.annotation.DataScope;
import com.bjpowernode.entity.TRole;
import com.bjpowernode.entity.TUser;
import com.bjpowernode.query.BaseQuery;
import com.bjpowernode.util.LoginInfoUtil;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;

import java.util.List;

/**
 * 数据范围切面类
 * 用于实现基于用户角色的数据权限控制，动态为查询添加数据过滤条件
 */
@Component  // 标记为Spring组件，使其被容器扫描并管理
@Aspect     // 声明为AOP切面类，用于定义切入点和通知
public class DataScopeAspect {
    /**
     * 环绕通知：在目标方法执行前后添加数据范围控制逻辑
     * @param joinPoint 连接点对象，包含目标方法信息
     * @return 目标方法的返回结果
     * @throws Throwable 执行过程中可能抛出的异常
     */
    @Around("@annotation(com.bjpowernode.annotation.DataScope)")  // 切入点：所有标注了@DataScope注解的方法
    public Object process(ProceedingJoinPoint joinPoint) throws Throwable {
        // 获取方法签名，用于获取注解信息
        MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();
        // 从方法上获取DataScope注解实例
        DataScope dataScope = methodSignature.getMethod().getAnnotation(DataScope.class);

        // 获取注解参数：表名和字段名
        String tableName = dataScope.tableName();
        String columnName = dataScope.columnName();

        // 获取当前登录用户信息
        TUser tUser = LoginInfoUtil.getCurrentLoginUser();
        // 获取用户拥有的角色列表
        List<TRole> tRoleList = tUser.getTRoleList();

        // 判断用户是否拥有管理员角色（角色名包含"admin"）
        boolean hasAdminRole = tRoleList.stream().anyMatch(role ->
                role.getRole().contains("admin"));

        // 如果不是管理员，则添加数据范围过滤
        if (!hasAdminRole) {
            // 获取方法的第一个参数（假设是查询参数对象）
            Object arg = joinPoint.getArgs()[0];
            // 判断参数是否为BaseQuery类型（基础查询类）
            if (arg instanceof BaseQuery) {
                BaseQuery baseQuery = (BaseQuery) arg;
                // 设置过滤SQL：表名.字段名 = 当前用户ID
                baseQuery.setFilterSQL(tableName + "." + columnName + " = " + tUser.getId());
            }
        }
        // 执行目标方法（原业务逻辑）
        Object proceed = joinPoint.proceed();
        // 返回目标方法的执行结果
        return proceed;
    }
}
